package com.company.cloud.acct.modules.app.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.acct.modules.api.response.AccountModel;
import com.company.cloud.acct.modules.app.controller.req.*;
import com.company.cloud.acct.modules.app.mapper.AcctAppMapper;
import com.company.cloud.acct.modules.app.service.AcctBankCardService;
import com.company.cloud.acct.modules.app.service.AcctCashService;
import com.company.cloud.acct.modules.app.service.AcctOpService;
import com.company.cloud.acct.modules.base.entity.AccountCashInfo;
import com.company.cloud.acct.modules.base.entity.AccountInfo;
import com.company.cloud.acct.modules.base.service.AccountCashInfoService;
import com.company.cloud.acct.modules.cache.models.*;
import com.company.cloud.acct.modules.cache.service.AcctCacheService;
import com.company.cloud.acct.modules.cache.utils.AcctConvertUtils;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.auth.annotation.Login;
import com.company.cloud.common.auth.annotation.StaffLogc;
import com.company.cloud.common.bean.BaseResult;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.AuthContextUtils;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.common.utils.LocalDateTimeUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

@Log4j2
@Login
@RestController
@RequestMapping("/app/acct/cash")
@Api(tags = "Acct_APP_账户提现")
public class AcctCashController {

    @Autowired
    private AcctCashService acctCashService;

    @Autowired
    private AcctOpService acctOpService;

    @Autowired
    private AcctBankCardService acctBankCardService;

    @Autowired
    private AccountCashInfoService accountCashInfoService;

    @Autowired
    private AcctCacheService acctCacheService;

    @Resource
    private AcctAppMapper acctAppMapper;

    @PostMapping("/cashAcct2Card2Config")
    @ApiOperation(value = "提现账户/银行卡/配置信息", response = Cash2Acct2Card2ConfigModel.class)
    public BaseResult cashAcct2Card2Config(@RequestParam("type") String type) {
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        AccountModel acct = acctOpService.getAcctInfo(userInfo.getId(), type);
        BankCardModel card = acctBankCardService.getBankCardDefByUser(userInfo.getId());
        CashConfigModel cashConfig = acctCacheService.getCompanyCashConfigCache(userInfo.getCompanyNo());

        Cash2Acct2Card2ConfigModel model = new Cash2Acct2Card2ConfigModel();
        model.setBankCard(card);
        model.setAcct(acct);
        model.setCashConfig(cashConfig);
        return BaseResult.ok(model);
    }

    @PostMapping("/apply")
    @StaffLogc(title = "Acct_APP_账户提现提现申请", action = "Acct_APP_账户提现提现申请", actionAdo = "Acct_APP_账户提现")
    @ApiOperation(value = "提现申请", response = BaseResult.class)
    public BaseResult apply(@RequestBody AcctCashApplyParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        acctCashService.apply(params, userInfo);
        return BaseResult.ok();
    }
    //Todo
    @PostMapping("/applyAdd")
    @ApiOperation(value = "线下打款提现申请", response = BaseResult.class)
    public BaseResult applyInfo(@RequestBody AcctCashApplyInfoParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        acctCashService.applyInfo(params, userInfo);
        return BaseResult.ok();
    }
    //Todo
    @PostMapping("/applyUpdate")
    @StaffLogc(title = "Acct_APP_账户提现线下打款提现审核", action = "Acct_APP_账户提现线下打款提现审核", actionAdo = "Acct_APP_账户提现")
    @ApiOperation(value = "线下打款提现审核", response = BaseResult.class)
    public BaseResult applyUpdate(@RequestBody AcctAccountInfoParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        acctCashService.applyUpdate(params, userInfo);
        return BaseResult.ok();
    }
    @PostMapping("/pointUpdate")
    @StaffLogc(title = "Acct_APP_账户提现、修改积分", action = "Acct_APP_账户提现、修改积分", actionAdo = "Acct_APP_账户提现")
    @ApiOperation(value = "修改积分", response = BaseResult.class)
    public BaseResult pointUpdate(@RequestBody AcctAccountInfoParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        acctCashService.pointUpdate(params, userInfo);
        return BaseResult.ok();
    }
    //Todo
    @PostMapping("/applyFreeze")
    @StaffLogc(title = "Acct_APP_账户提现、后台冻结余额与恢复余额", action = "Acct_APP_账户提现、后台冻结余额与恢复余额", actionAdo = "Acct_APP_账户提现")
    @ApiOperation(value = "后台冻结余额与恢复余额", response = BaseResult.class)
    public BaseResult applyFreeze(@RequestBody AcctAccountInfoParam params) {
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        acctCashService.applyFreeze(params, userInfo);
        return BaseResult.ok();
    }

    @PostMapping("/myQuery")
    @ApiOperation(value = "我的提现记录查询", response = AcctCashModel.class)
    public BaseResult myQuery(@RequestBody AcctCashParam params) {

        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        IPage<AccountCashInfo> page = accountCashInfoService.page(new Page<>(params.getPage(), params.getRows()), new QueryWrapper<AccountCashInfo>()
                .eq("user_id", userInfo.getId())
                .eq("company_no", userInfo.getCompanyNo())
                .in(!CollectionUtils.isEmpty(params.getTypes()), "type", params.getTypes())
                .eq(CheckUtils.hasText(params.getMonth()), "DATE_FORMAT(cdt,'%Y-%m')", params.getMonth())
                .orderByDesc("cdt")
        );
        Map<Integer, BankCardModel> cardMap = acctCacheService.getBankCardMapByUser(userInfo.getId());
        IPage<AcctCashModel> data = page.convert(new Function<AccountCashInfo, AcctCashModel>() {
            @Override
            public AcctCashModel apply(AccountCashInfo entity) {
                return AcctConvertUtils.getAcctCashModel(entity, cardMap);
            }
        });
        return BaseResult.ok(data);
    }

    @PostMapping("/myQueryByMonth")
    @ApiOperation(value = "我的提现记录月统计", response = AcctCashMonthStatModel.class)
    public BaseResult myQueryByMonth(@RequestBody AcctMergeParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        List<AcctCashMonthStatModel> list = acctAppMapper.queryAcctCashStatMonth(new QueryWrapper<AcctCashMonthStatModel>()
                .eq("user_id", userInfo.getId())
                .eq("company_no", userInfo.getCompanyNo())
                .in("type", params.getTypes())
                .groupBy("DATE_FORMAT(cdt,'%Y-%m')")
        );
        return BaseResult.ok(list);
    }

    @PostMapping("/myQueryByMonth2Item")
    @ApiOperation(value = "我的提现记录月统计(含明细)", response = AcctCashMonthStatModel.class)
    public BaseResult myQueryByMonth2Item(@RequestBody AcctCashByMonth2ItemParam params) {
        ValidatorUtils.validate(params);
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        List<AccountCashInfo> cashList = accountCashInfoService.list(
                new QueryWrapper<AccountCashInfo>()
                        .eq("user_id", userInfo.getId())
                        .in("type", params.getTypes())
                        .orderByDesc("cdt")
        );
        if (CollectionUtils.isEmpty(cashList)) {
            return BaseResult.ok();
        }

        Map<Integer, BankCardModel> cardMap = acctCacheService.getBankCardMapByUser(userInfo.getId());
        List<AcctCashModel> acctCashList = new ArrayList<>();
        BigDecimal totalFund = BigDecimal.ZERO;
        BigDecimal totalFundReal = BigDecimal.ZERO;
        BigDecimal totalTaxFee = BigDecimal.ZERO;
        BigDecimal totalServiceFee = BigDecimal.ZERO;

        Map<String, AcctCashMonthStatModel> map = new HashMap<String, AcctCashMonthStatModel>();
        for (AccountCashInfo cashInfo : cashList) {
            String month = LocalDateTimeUtils.format_yyyyMM(cashInfo.getCdt());
            AcctCashMonthStatModel acmsm = map.get(month);
            if (acmsm == null) {
                acmsm = new AcctCashMonthStatModel();
                acmsm.setMonth(month);
                acmsm.setTotalFund(BigDecimal.ZERO);
                acmsm.setTotalFundReal(BigDecimal.ZERO);
                acmsm.setTotalTaxFee(BigDecimal.ZERO);
                acmsm.setTotalServiceFee(BigDecimal.ZERO);
                map.put(month, acmsm);
            }
            acmsm.setTotalFund(acmsm.getTotalFund().add(cashInfo.getFund()));
            acmsm.setTotalFundReal(acmsm.getTotalFundReal().add(cashInfo.getFundReal()));
            acmsm.setTotalTaxFee(acmsm.getTotalTaxFee().add(cashInfo.getTaxFee()));
            acmsm.setTotalServiceFee(acmsm.getTotalServiceFee().add(cashInfo.getServiceFee()));
            acmsm.addAcctCash(AcctConvertUtils.getAcctCashModel(cashInfo, cardMap));
        }
        List<AcctCashMonthStatModel> data = new ArrayList<AcctCashMonthStatModel>();
        map.forEach((k, v) -> {
            data.add(v);
        });
        return BaseResult.ok(data);
    }

    @GetMapping("/get")
    @ApiOperation(value = "提现明细", response = AcctCashModel.class)
    public BaseResult get(@RequestParam("sn") String sn) {
        LoginSimpleUserInfo userInfo = AuthContextUtils.getUser();
        Map<Integer, BankCardModel> cardMap = acctCacheService.getBankCardMapByUser(userInfo.getId());
        AccountCashInfo entity = accountCashInfoService.getById(sn);
        if (null == entity) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }
        AcctCashModel data = AcctConvertUtils.getAcctCashModel(entity, cardMap);
        return BaseResult.ok(data);
    }

}
